home *** CD-ROM | disk | FTP | other *** search
- ; Micro Cornucopia Magazine Issue #49
- ; PostScriptals article code
- ;
- ; This is a pruned version of Harlan Stockman's 386 specific code originally
- ; run in Micro Cornucopia Issue #43. I used it for the PostScriptal article
- ; in Issue #49. The code that's left has not been altered - I just removed
- ; the stuff I didn't need and reassembled with DeSmet.
- ; Larry Fogg - June 28, 1989
-
- ; This file is mand.a ... DeSmet asm88 functions for fr386.c,
- ; a fixed-pt 386 version of Mandelbrot ...
- ; mandwhile.a replaces inner "while" loop of mandelbrot calculation...
-
- ;==============386-SPECIFIC FUNCTIONS===================================
- ; int mandwhile(long P, long Q, int nmax)
- ; Performs all calculations for "while" loop in L.Fogg's mandel()
- ; function, using fixed pt math with binary pt between bits 23 and 24...
- ;
- ; FOR: DeSmet C/asm88 small case...
- ;
- ; In REAL MODE; uses 32-bit overrides on register length and addressing to
- ; gain performance of 32-bit regs and instructions...
- ; Returns # iterations before divergence (16-bit int returned in ax).
- ; Note 1/3 rd of instructions are for rounding, to get small amount extra
- ; accuracy; if you aren't that picky, dump these instructions for 10% or more
- ; extra speed...
- ;
- ; REGISTERS: ebp ...ytemp at top of loop, modulus_sqrd
- ; at bottom of loop
- ; edx:eax ...multiplication and temporary storage
- ; edi ...P
- ; esi ...Q
- ; ebx ...x
- ; ecx ...y
- ;
- ; RETURNS stopping number of iterations in ax.
-
- dseg
- public counter
- counter dw 0
- cseg
- public mandwhile_
- mandwhile_:
- db 66h, 55h ;push ebp
- ;---get P ...
- db 67h, 66h, 8Bh, 7Ch, 24h, 06h ;mov edi,dword [esp+6]
- ;---get Q ...
- db 67h, 66h, 8Bh, 74h, 24h, 0Ah ;mov esi,dword [esp+10]
- ;---get nmax...
- db 67h, 8Bh, 44h, 24h, 0Eh ;mov ax,word [esp+14]
- ;---initialize counter ...
- mov word counter,ax
- ;---zero out x and y storage ...
- db 66h, 33h, 0DBh ;xor ebx,ebx
- db 66h, 33h, 0C9h ;xor ecx,ecx
-
- looper: ;---ytemp=x*y---
- db 66h, 8Bh, 0C3h ;mov eax,ebx
- db 66h, 0F7h, 0E9h ;imul ecx
- db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H ;for rounding...
- db 66h, 83h, 0D2h, 00h ;adc edx,0 ;for rounding...
- db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8 ;div by 2**24...
- db 66h, 8Bh, 0EAh ;mov ebp,edx
- ;---x=x*x - y*y + P------
- db 66h, 8Bh, 0C3h ;mov eax,ebx
- db 66h, 0F7h, 0EBh ;imul ebx
- db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
- db 66h, 83h, 0D2h, 00h ;adc edx,0
- db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
- db 66h, 8Bh, 0DAh ;mov ebx,edx
- ;---
- db 66h, 8Bh, 0C1h ;mov eax,ecx
- db 66h, 0F7h, 0E9h ;imul ecx
- db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
- db 66h, 83h, 0D2h, 00h ;adc edx,0
- db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
- db 66h, 2Bh, 0DAh ;sub ebx,edx
- db 66h, 03h, 0DFh ;add ebx,edi ;add P...
- ;---y=(ytemp<<1) + Q----
- db 66h, 0D1h, 0E5h ;shl ebp,1
- db 66h, 03h, 0EEh ;add ebp,esi ;add Q...
- db 66h, 8Bh, 0CDh ;mov ecx,ebp
- ;---modsqrd = x*x + y*y---
- db 66h, 8Bh, 0C3h ;mov eax,ebx
- db 66h, 0F7h, 0EBh ;imul ebx
- db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
- db 66h, 83h, 0D2h, 00h ;adc edx,0
- db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
- db 66h, 8Bh, 0EAh ;mov ebp,edx
- ;---
- db 66h, 8Bh, 0C1h ;mov eax,ecx
- db 66h, 0F7h, 0E9h ;imul ecx
- db 66h, 05h, 00h, 00h, 80h, 00h ;add eax,800000H
- db 66h, 83h, 0D2h, 00h ;adc edx,0
- db 66h, 0Fh, 0A4h, 0C2h, 08h ;shld edx,eax,8
- db 66h, 03h, 0EAh ;add ebp,edx
- ;---test if modsqrd > "4"---(67108864 = 4*(1 << 24))---
- db 66h, 81h, 0FDh, 00h,00h,00h,04h ;cmp ebp,67108864
- jae home
- dec word counter
- jnz looper
- home: mov ax,word counter
- neg ax
- db 67h, 03h, 44h, 24h, 0Eh ;add ax, word [esp+14]
- db 66h, 5Dh ;pop ebp
- ret
-
-
- ; long muldiv(long A, int b, int c)
- ; Multiplies 32-bit "a" by 16-bit "b", then divides by
- ; 16-bit "c" such that abs(c) >= abs(b)...NO CHECK FOR 0 DIVISOR...
- ;
- ; NOTE how DeSmet figures stack upon entry:
- ; 16-bit return address at sp, "A" at sp+2, b at sp+6, c at sp+8 ...
- ;
- ; REGISTERS: eax ...initially holds "A"
- ; ebx ...holds b
- ; ecx ...holds c
- ; edx:eax ...product A*b (before idiv)
- ;
- ; RETURNS long result in dx:ax.
-
- cseg
- public muldiv_
- muldiv_:
- db 67h,66h,8bh,44h,24h,02h ;mov eax,dword ptr [esp+2]
- db 67h,66h,0fh,0bfh,5ch,24h,06h ;movsx ebx,word ptr [esp+6]
- db 67h,66h,0fh,0bfh,4ch,24h,08h ;movsx ecx,word ptr [esp+8]
- db 66h,0f7h,0ebh ;imul ebx
- db 66h,0f7h,0f9h ;idiv ecx
- db 66h,0fh,0a4h,0c2h,10h ;shld edx,eax,16
- ret ;short return...
-
-
-
-
-
- ;==============TEST FOR 386===============================
- ; int is_386()
- ; 2-20-88 checks for presence of 386 -- returns 0 if not found, else
- ; returns non-zero ...
- ; note short return for DeSmet asm88 small case ...
- ; REF: Juan E. Jimenez, Turbo Technix Jan/Feb 88, p. 55 ...
-
- cseg
- public is_386_
- is_386_: pop di ;return address ...
- pushf
- xor ax,ax
- push ax
- popf
- pushf
- pop ax
- and ax,8000h
- sub ax,8000h
- jz home2
- ;------
- mov ax,7000h ;if here, either 286 or 386 ...
- push ax
- popf
- pushf
- pop ax
- and ax,7000h
- home2: jmp di
-
-
- ;==============DESMET KEYBOARD POLLING ROUTINES===========
- ; int scr_ci() and int scr_csts()
- ; These functions read the keyboard; scr_ci() waits until
- ; a key is typed, and returns the key; scr_csts() does not wait and returns
- ; 0 if no key is available. Unlike DeSmet functions ci() and csts(), these
- ; functions can read and translate extended keyboard codes (e.g., cursors
- ; and function keys). NOTE these are slightly faster than scr_ci() and
- ; scr_csts() given in DeSmet's optional PCIO.a file .
- ;
- ; FOR TURBO C: replace with combination of kbhit() and getch()...
-
- dseg
- ; TABLES to convert (scan_code - 59) to char code...
- table1: db 210 ;F1 scan= 59
- db 211 ;F2 60
- db 212 ;F3 61
- db 213 ;F4 62
- db 214 ;F5 63
- db 215 ;F6 64
- db 216 ;F7 65
- db 217 ;F8 66
- db 218 ;F9 67
- db 219 ;F10 68
- db 0 ;NumLock 69 ...not used
- db 0 ;ScrollL 70 ...not used
- db 200 ;bol_char 71
- db 30 ;up_arrow 72
- db 202 ;page_up 73
- db 0 ;grey(-) 74 ...not used
- db 29 ;left_arrow 75
- db 0 ;NumPad5 76 ...not used
- db 28 ;right_arrow77
- db 0 ; 78 ...not used
- db 201 ;eol_char 79
- db 31 ;down_arrow 80
- db 203 ;page_down 81
- db 206 ;Insert 82
- db 207 ;Delete 83
- public table2
- table2: db 209 ;left_word 115
- db 208 ;right_word 116
- db 205 ;end_of_file117
- db 0 ; 118 ..not used
- db 204 ;begin_file 119
- cseg
- public scr_ci_
- scr_ci_: push bp
- mov ah,0
- int 16H
- cmp al,0
- jne not_special
- mov bl,ah
- xor bh,bh
- cmp bx,114
- ja use_table2
- sub bx,59
- mov al,byte table1[bx]
- jmp not_special
- use_table2: sub bx,115
- mov al,byte table2[bx]
- not_special: xor ah,ah
- pop bp
- ret
-
-
- public scr_csts_
- scr_csts_: push bp
- mov ah,1
- int 16H
- mov ax,0
- jz csts_over
- call scr_ci_
- csts_over: pop bp
- ret
-
- ;==============LOG COLOR TRANSFORM===================================
- ; 2-20-88 transform(int iter, int switchpt) ... DeSmet asm88 ...
- ; for frac386.c ...
- ; ...returns the "color" then anded with (maxcolors-1)...
- ; converts the iterations returned by mand() to a log scaling, starting at
- ; the switchpt. Equiv. to C coding:
- ; if(iter < switchpt) color = iter;
- ; else for(color=i=switchpt,inc=1; i<iter; i=switchpt+(inc<<=1),color++);
- ; ...However, 386 is so fast we need to translate to asm to get full benefit!
-
- cseg
- public transform_
- transform_: pop di ;return address...
- pop cx ;iter...
- pop bx ;switchpt...
- sub sp,4 ;required by DeSmet for short return...
- cmp cx,bx
- ja do_loop
- mov ax,cx
- jmp di ;short return...
- ;------
- do_loop: mov ax,bx ;init color (ax) with switchpt...
- mov si,2 ;si = inc... (originally = 1)
- mov dx,bx ;init i (dx) with switchpt...
- ;------
- loopit: cmp dx,cx ;compare i (dx) to iter (cx)...
- jge done
- shl si,1 ;inc <<= 1...
- mov dx,bx
- add dx,si ;i = switchpt + inc...
- inc ax
- jmp loopit
- ;------
- done: jmp di ;short return, color in ax...
-
-